﻿using CSPointer;
//using ICSharpCode.SharpZipLib.GZip;
//using ICSharpCode.SharpZipLib.Zip;
//using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine;
//using zlib;
using Free.Ports.zLib;

public class bits:MonoBehaviour
{
    /*
下面的宏用来从数字中取出某些特定位
*/
    private static uint _bitm(uint v,int a,int b,int size)
    {
        return (((v) << ((size) - (b) - 1)) >> ((size) - (b) - 1 + (a))); //辅助宏
    }

    public static uint bit1(uint v, int a)
    {
        return (((v) >> (a)) & 0b1);									   //取一个数字的第a位
    }

    private static uint bitm64(uint v, int a,int b)
    {
        return _bitm(v, a, b, 64);										   //取一个64位数字的第[a:b]位
    }

    private static uint bitm(uint v, int a, int b)
    {
        return _bitm(v, a, b, 32);										   //取一个32位数字的第[a:b]位
    }

    public static uint bitm16(uint v, int a, int b)
    {
        return _bitm(v, a, b, 16);										   //取一个16位数字的第[a:b]位
    }

    private static uint bitm8(uint v, int a, int b)
    {
        return _bitm(v, a, b, 8);										   //取一个8位数字的第[a:b]位
    }

    private static uint bitm4(uint v, int a, int b)
    {
        return _bitm(v, a, b, 4);										   //取一个4位数字的第[a:b]位
    }

    /*
下面的宏用来处理符号扩展
符号扩展： 将一个不足32位的数字连同符号位一起扩展到32位
*/
    //private static int val_bits(uint val)
    //{
    //    //val.GetType().
    //    return ((uint)sizeof(val) << 3);										//通过数字类型类型计算一个数字的位数
    //}

    public static int sign_extend(uint val, int val_bits)
    {
        return (((int)((val) << (32 - (val_bits)))) >> (32 - (val_bits))); //带符号扩展，传递值和值当前的位数
    }

    //public static int sign_extend_e(uint val)
    //{
    //    //val.GetType().
    //    return (((int)((val) << (32 - val_bits(val)))) >> (32 - val_bits(val)));//带符号扩展，传递值和值当前的位数 (注意：如果val的位数不是8、16请调用sign_extend手动传递位数)
    //}

    /*
下面的命令用来简化指令读取
*/

    public static uint inst_bm(uint inst, int from, int to)
    {
        return bitm(inst, from, to);//读取指令的某些位
    }

    public static uint inst_b1(uint inst, int pos)
    {
        return bit1(inst,pos); //读取指令的某一位
    }

    public static uint inst_b4(uint inst, int from)
    {
        return bitm(inst, from, from+3); //读取指令的某4位
    }

    public static uint inst_b8(uint inst, int from)
    {
        return bitm(inst, from, from + 7); //读取指令的某8位
    }

    public static uint inst_b16(uint inst, int from)
    {
        return bitm(inst, from, from + 15); //读取指令的某16位
    }

    public static uint inst_b24(uint inst, int from)
    {
        return bitm(inst, from, from + 23); //读取指令的某24位
    }

}


public unsafe class arms : bits
{
    public static vm_info_st vm;
    public static mrp_reader_t reader;
    public static byte* vm_mem_buf;
    public static byte* font_buf;
    public static byte[] font_buf_m;
    public static uint vm_mem_poffset(uint n)
    {
       // uint i = vm_mem_offset(&vm.mem->mr_func_tab_p) + ((n) << 2);
        uint i = vm_mem_offset(vm.mem->mr_func_tab_p) + ((n) << 2);
        return i;
    }

    public static uint vm_mem_offset(byte[] n, uint index = 0)//用来获取某些值得内存偏移
    {
        return vm_mem_offset((byte*)getBytePtr(n), index);
    }

    public static uint vm_mem_offset(void* n, uint index = 0)//用来获取某些值得内存偏移
    {
        uint i = (uint)((byte*)(n) - vm.cpu.mem.bufferP);
        return i+ index;
    }

    public static uint* vmreg(int v)
    {
       fixed (uint* r= &vm.cpu.registers[v])
        {
            return r;
        }
    }
    public static uint vmstack(int i)
    {
        return (*((uint*)(vm_mem_buf + vm.cpu.registers[DefineConstants.r_sp]) + i));
    }

    public static byte* vmpt_real(uint add)
    {
        return vm.cpu.mem.bufferP + add;
    }

    public static void println(string info)
    {
        print(info);
    }

    public static void logi(string info, object v1 = null, object v2 = null, object v3 = null, object v4 = null, object v5 = null, object v6 = null)
    {
        if (GameStart.isPrint)
            print(string.Format(info + "   v1:{0}  v2:{1}  v3:{2}  v4:{3}  v6:{4}", v1, v2,v3,v4,v5));
    }

    public static void logi(string info, object v1 , object v2, void* v3)
    {
        if (GameStart.isPrint)
            print(string.Format(info + "   v1:{0}  v2:{1}", v1, v2));
    }

    public static void logw(string info, object v1 = null, object v2 = null, object v3 = null, object v4 = null, object v5 = null, object v6 = null)
    {
        print(string.Format(info + "   v1:{0}  v2:{1}", v1, v2));
    }

    public static void loge(string info, object v1 = null, object v2 = null, object v3 = null, object v4 = null, object v5 = null, object v6 = null)
    {
        print(string.Format(info));
    }

    public static void usleep(uint time)
    {
        if (GameStart.isLog)
            UnityEngine.Debug.Log("sleep : " + time);
    }

    public static int logMax = 10;
    public static int logIndex = 0;
    public static uint Inst;

    public static void loginst(string info, uint v1 = 0, string v2 = "")
    {
        if (GameStart.isLog)
        {
            //if (logMax > 0)
            //{
            //    logIndex++;
            //    log.Add(logIndex.ToString() + "   " + Inst.ToString(), "   " + info);
            //    logMax--;
            //}
            //else
            //{
            //    if (logMax == 0)
            //    {
            //        logMax--;
            //        saveLog();
            //    }
            //}
            Debug.Log(string.Format(info + "   v1:{0}  v2:{1}", v1, v2));
        }
        
        
    }

    public static Dictionary<string, string> log = new Dictionary<string , string>();

    public static void saveLog()
    {
        string result1 =Application.dataPath+ @"\..\"+GameStart.MrpFileName+".txt";//结果保存到F:\result1.txt
        if (File.Exists(result1))
            File.Delete(result1);
        FileStream fs = new FileStream(result1, FileMode.Append);

        StreamWriter wr =new StreamWriter(fs);
        foreach (var logs in log)
        wr.WriteLine(logs.Key .ToString ()+logs.Value .ToString ());
        wr.Close();
    }

    public static void println(string info, object v1 = null, object v2 = null)
    {
        if (GameStart.isPrint)
         print(string.Format(info + "   v1:{0}  v2:{1}", v1, v2));
    }

    public static void logsysc(string info, string v1 = "", string v2 = "")
    {
        print(string.Format(info + "   v1:{0}  v2:{1}", v1, v2));
    }

    // Start is called before the first frame update
    void Start()
    {
        //byte[] a = new byte[5] { 1, 2, 3, 4, 5 };
        //IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(a, 0);
        //IntPtr p1 = ptr + 2;
        //byte b = Marshal.ReadByte(p1);
    }

    // Update is called once per frame
    void Update()
    {

    }

    public static int powl(int x, uint y)
    {
        return (int)Mathf.Pow(x, y);
    }

    public static int powl(int x, int y)
    {
        return (int)Mathf.Pow(x, y);
    }

    public static int gettimeofday(timeval o, object v1)
    {
        //o.tv_sec = (int)(Time.time*1000);
        o.tv_sec = Environment.TickCount;
        //o.tv_usec = (long)(o.tv_sec / 1000f);
        o.tv_usec = o.tv_sec / (TimeSpan.TicksPerMillisecond / 1000);
        return 0;
    }

    public unsafe static byte* memcpy(ushort* dest, int destIndex, ushort* src, int srcIndex, int len)
    {
        return (byte*)memcpy(dest + destIndex, src + srcIndex, (uint)len);
        //return (byte*)memcpy((byte*)dest+destIndex,(byte*)src+srcIndex, (uint)len);
    }

    public unsafe static byte* memcpy(byte[] dest, uint destIndex, byte[] src, uint srcIndex, uint len)
    {
        return memcpy((byte*)getBytePtr(dest, destIndex), (byte*)getBytePtr<byte>(src), srcIndex, len);
    }

    public unsafe static byte* memcpy(byte* dest, uint destIndex, byte[] src, uint srcIndex, uint len)
    {
        return memcpy(dest + destIndex, (byte*)getBytePtr<byte>(src), srcIndex, len);
    }

    public unsafe static byte* memcpy(byte[] dest, uint destIndex, void* src, uint len)
    {
        return (byte*)memcpy((void*)getBytePtr(dest, destIndex), src, (uint)len);
    }

    public unsafe static byte* memcpy(byte* dest, byte* src, uint srcIndex, uint len)
    {
        return (byte*)memcpy(dest, (void*)(src + srcIndex), (uint)len);
    }

    public unsafe static byte* memcpy(void* dest, byte[] src, uint srcIndex, uint len)
    {
        return (byte*)memcpy(dest, (void*)getBytePtr(src, srcIndex), (uint)len);
    }

    public unsafe static sbyte* memcpy(sbyte* dest, string src, int len)
    {
        byte[] date=null;
        try
        {
            date = StringTobyte(src);
            if(len>date.Length)
            {
                Debug.LogError("memcpy data error");
                return dest;
            }
            else if(len<date.Length)
            {
                len = date.Length;
                Debug.LogWarning("memcpy len<date.Length");
            }
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
            return dest;
        }
        // date = Str_String(src);
       
        return (sbyte*)memcpy(dest, (void*)getBytePtr(date), (uint)date.Length);
    }

    public unsafe static byte* memcpy(uint destIndex, byte[] src, uint len)
    {
        //Marshal.Copy(src,0, getBytePtr(vm.cpu.mem .buffer ,destIndex),(int)len );
        //return null;
        return (byte*)memcpy(vm_mem_buf + destIndex, (void*)getBytePtr(src), (uint)len);
    }

    public static void* memcpy(void* dest, void* src, uint n)
    {
        //sbyte* d = (sbyte*)dest;
        //sbyte* s = (sbyte*)src;
        //int* di;
        //int* si;
        //uint r = n % 4;

        //while (r-- != 0)
        //    *d++ = *s++;
        //di = (int*)d;
        //si = (int*)s;
        //n /= 4;

        //for (int i = 0; i < n; i++)
        //{
        //    di[i] = si[i];
        //}
        //return dest;


        return memcpy(dest, src, (long)n);
    }

    public static void* memcpy(void* dst, void* src, long size)
    {
        if(size<0)
        {
            Debug.LogError("memcpy size miss");
        }
        byte* psrc;
        byte* pdst;

        if (null == dst || null == src)
        {
            return null;
        }

        if ((src < dst) && (byte*)src + size > (byte*)dst) // 自后向前拷贝
        {
            psrc = (byte*)src + size - 1;
            pdst = (byte*)dst + size - 1;
            while (size-- != 0)
            {
                *pdst-- = *psrc--;
            }
        }
        else
        {
            psrc = (byte*)src;
            pdst = (byte*)dst;
                while (size-- != 0)
                {
                    *pdst++ = *psrc++;
                }
        }

        return dst;
    }

    public static void* memmove(void* dest, void* src, uint n)
    {
        if (n == 0)
        {
            return null;
        }

        /* 验证参数 */
        if (dest == null) return null;
        if (src == null) return null;

        byte* psrc = (byte*)src;
        byte* pdest = (byte*)dest;

        /*检查是否有重叠问题 */
        if ((dest <= psrc) || (pdest >= psrc + n))
        {
            /*正向拷贝*/
            for (int i = 0; i < n; i++)
            {
                *pdest = *psrc;
                psrc++;
                pdest++;
            }
        }
        else
        {
            /*反向拷贝*/
            psrc += n;
            pdest += n;
            for (int i = 0; i < n; i++)
            {
                psrc--;
                pdest--;
                *pdest = *psrc;

            }
        }
        return dest;
    }

    //    public static void* memmove(void* dest, void* src, uint count)
    //{
    //	if (0 == count) return null;
    //	if (null == dest || null == src)  return null;

    //	char* dest_ = (char*)dest;;
    //	char* src_ = (char*)src;
    //	if ((dest_ > src_) && (dest_<src_ + count))//判断内存重叠时的情况反向拷贝（如果正向，会改变模板原来的值）
    //	{

    //		while (count-->0)
    //			*(dest_ + count) = *(dest_ + count);
    //	}
    //	else //不重叠情况正向拷贝（如果反向，也会改变模板原来的值）
    //	{
    //		while (count-->0)

    //            * dest_++ = * src_++;
    //	}
    //	return dest;
    //}

    public static void* memmove(void* dest, uint destIndex, void* src, uint srcIndex, uint n)
    {
        return memmove((byte*)dest + destIndex, (byte*)src + srcIndex, n);
    }

    public static void* memmove(byte[] dest, uint destIndex, byte[] src, uint srcIndex, uint n)
    {
        return memmove((void*)getBytePtr(dest, destIndex), (void*)getBytePtr(src, srcIndex), n);
    }

    public static void* memmove(byte[] dest, long destIndex, byte[] src, long srcIndex, long n)
    {
        return memmove((void*)getBytePtr(dest, (uint)destIndex), (void*)getBytePtr(src, (uint)srcIndex), (uint)n);
    }

    public static void memset(void* dest, sbyte value, uint len)
    {
        sbyte* p = (sbyte*)dest;
       
        for (int i = 0; i < len; i++)
            p[i] = value;
    }

    public static void memset(object dest, uint destIndex, uint len)
    {}

    /// <summary>
    /// 比较字节数组
    /// </summary>
    /// <param name="b1">字节数组1</param>
    /// <param name="b2">字节数组2</param>
    /// <returns>如果两个数组相同，返回0；如果数组1小于数组2，返回小于0的值；如果数组1大于数组2，返回大于0的值。</returns>
    public static int MemoryCompare(byte[] b1, byte[] b2)
    {
        int result = 0;
        if (b1.Length != b2.Length)
            result = b1.Length - b2.Length;
        else
        {
            for (int i = 0; i < b1.Length; i++)
            {
                if (b1[i] != b2[i])
                {
                    result = (int)(b1[i] - b2[i]);
                    break;
                }
            }
        }
        return result;
    }

    public static uint memcmp(byte[] dest, uint destIndex, byte[] src, uint srcIndex, uint len)
    {
        byte[] newDest = new byte[len];
        byte[] newSrc = new byte[len];
        for (int i = 0; i < len; i++)
        {
            newDest[i] = dest[destIndex + i];
            newSrc[i] = src[srcIndex + i];
        }

        return (uint)MemoryCompare(newDest, newSrc);
    }

    public static uint memchr(byte[] dest, uint destIndex, byte value, uint len)
    {
        uint ret = 0;
        int n = (int)len;
        //string str = String(dest, destIndex,(int)50);
        //char c = (char)value;
        Debug.LogWarning("memchr");
        if(n<=0)
        {
            return ret;
        }
        for (uint i = 0; i < len; i++)
        {
            uint index = destIndex + i;
            if (dest [index] == value)
            {
               return index;
            }
        }
        return ret;
    }

    public static void snprintf(ref string dsmFullPath, string dest, string dir, string dsm, string fileName)
    {
        dsmFullPath = dir + "/" + dsm + "/" + fileName;
    }

    public static sbyte* strcpy(sbyte* dst,sbyte* src, uint len=0)
    {
        sbyte* ret = dst;  //[3]
        if(len>0)
        {
            while(len>0)
            {
                len--;
                *dst++ = *src++;
            }
        }
        else
        while ((*dst++ = *src++) != '\0') ; //[4]

        return ret;
    }

    public static sbyte* strcat(sbyte* dst, sbyte* src, uint len = 0)
    {
        uint index= _strnlen_s(dst);
        return strcpy(dst + index, src, len);
    }

    public static int strncmp(byte* str1, byte* str2, int n)
    {
        if (n == 0)   //n=0时，无字符要比，直接return 0
            return 0;
        while (--n != 0 && *str1 != 0 && *str1 == *str2) //当字符相等且不为’\0‘时比较下个字符，知道n=0比完
        {
            str1++;
            str2++;
        }
        return *str1 - *str2;//字符不相等时，（*str1 - *str2）可以满足返回值正负的需求
    }


    public static void free(object value)
    {
        if (GameStart.isPrint)
            UnityEngine.Debug.Log("free");
       // Marshal.FreeHGlobal(getMemoryPtr(value)); 
    }

    public static void free(void* value)
    {
        if (GameStart.isLog)
            UnityEngine.Debug.Log("free");
        //Marshal.FreeHGlobal((IntPtr)value);
    }

    //public static string GetString(byte* scr, int index)
    //{
    //    return Encoding.Default.GetString(PtoS(scr, index));
    //}

    public static IntPtr getMemoryPtr(object o) // 获取引用类型的内存地址方法  
    {
        GCHandle h = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
        IntPtr addr = GCHandle.ToIntPtr(h);
        UnityEngine.Debug.Log("0x" + addr.ToString("X"));
        return addr;
    }

    public static uint write(int v, uint p, uint len)
    {
        if (file[v - 3] != null)
        {
            byte[] date = new byte[len];
            memcpy(date, 0, vm.cpu.mem.buffer, p, len);
            FILE f = (FILE)file[v - 3];
            f.Write(date, 0, (int)len);
            return (uint)(len);
        }
        else
        {
            Debug.LogError("write error");
        }
        return uint.MaxValue;

    }
    public static bool isTest;
    public static uint read(int v, void* p, uint len)
    {
        //IntPtr ptr = getBytePtr(vm.cpu.mem.buffer, p);
        //Marshal.Copy(vm.cpu.mem.buffer, (int)v, ptr, (int)len);
        if (file[v-3] != null)
        {
            uint num = len;
            byte[] date = new byte[len];
            //num = (uint)file[v - 3].Read(date, 0, (int)len);
            for (int i = 0; i < len; i++)
            {
                date[i] = (byte)file[v - 3].ReadByte();
            }
            memcpy(p, date, 0, num);
            return (uint)num;
        }
        else
        {
            Debug.LogError("read error");

        }

        return uint.MaxValue;
    }

    // internal secure strlen
	// return The length of the string (excluding the terminating 0) limited by 'maxsize'
    internal static uint _strnlen_s(sbyte* str, uint maxsize = 200)
    {
        //C++ TO C# CONVERTER CRACKED BY X-CRACKER 2017 TODO TASK: Pointer arithmetic is detected on this variable, so pointers on this variable are left unchanged:
        sbyte* s;
        //string ss = new string(str);
        sbyte c = (sbyte)'\0';
        for (s = (sbyte*)str; (*s) != c && (maxsize--) != 0; ++s) { }
        return (uint)(s - str);
        // return (uint)str.Length;
    }

    public static int SEEK_SET = 0;
    public static int SEEK_CUR = 1;
    public static int SEEK_END = 2;

    public static int lseek(int v, int pos, int method)
    {
        if (file[v - 3] != null)
        {
            return (int)file[v-3].Seek(pos, (SeekOrigin)method);
        }
        return -1;
    }

    public static int remove(string str)
    {
        string path = FormatPathString(str);
        try
        {
            if (File.Exists(path))
            {
                if (files.ContainsKey(path))
                {
                    FILE file = files[path];
                    file.Dispose();
                    files.Remove(path);
                }
                File.Delete(path);
                Debug.LogWarning(string.Format("remove  {0}  ", str));

            }
            else
            {
                return 0;
            }
        }catch
        {
            return -1;
        }
          
        return 0;
    }

    public static int rename(string fullpathname_1, string fullpathname_2)
    {
        //Debug.LogWarning(string.Format("rename  {0} {1} ",fullpathname_1,fullpathname_2));
        try
        {
            Debug.LogWarning("rename " + fullpathname_1 + "  to  " + fullpathname_2);
            string dest = FormatPathString(fullpathname_2);
            string sour = FormatPathString(fullpathname_1);
            if (!File.Exists(dest))
            {
                if (File.Exists(sour))
                    File.Move(sour, dest);
                else
                    return -1;
            }
            else
            {
                return 0;
            }
            
        }
        catch
        {
            Debug.LogWarning("rename error "+ fullpathname_1+"  to  "+fullpathname_2);
            return -1;
        }
        return 0;
    }

    public static int mkdir(string fullpathname)
    {
        try
        {
            Directory.CreateDirectory(FormatPathString(fullpathname));
        }
        catch
        {
            return -1;
        }
        return 0;
    }

    public static int rmdir(string fullpathname)
    {
        try
        {
            Directory.Delete(FormatPathString(fullpathname));
        }
        catch
        {
            return -1;
        }
        return 0;
    }

    public static int strcasecmp(string fullpathname, string sdcard_dir)
    {
        return fullpathname.Equals(sdcard_dir)?-1:0;
    }

    public static IntPtr getBytePtr<T>(T[] data, uint index = 0) // 获取byte的内存地址方法  
    {
        IntPtr addr = Marshal.UnsafeAddrOfPinnedArrayElement<T>(data, (int)index);
        return addr;
    }

    //public static void Insert(object insertObj, byte[] date, uint index)
    //{
    //    //Marshal.StructureToPtr(insertObj, Marshal.UnsafeAddrOfPinnedArrayElement(date, (int)index), false);
    //    fixed (byte* arrptr = &(date[index]))
    //    {
    //        Marshal.StructureToPtr(insertObj, (IntPtr)arrptr, true);
    //    }
    //}

    //private static unsafe byte[] ConvertStruct<T>(ref T str) where T : struct
    //{
    //    int size = Marshal.SizeOf(str);
    //    var arr = new byte[size];

    //    fixed (byte* arrPtr = arr)
    //    {
    //        Marshal.StructureToPtr(str, (IntPtr)arrPtr, true);
    //    }

    //    return arr;
    //}

    //public static unsafe object BytesToStuct(byte* bytes, Type type)
    //{
    //    int size = Marshal.SizeOf(type);
    //    byte[] date = new byte[size];
    //    Marshal.Copy((IntPtr)bytes, date, 0, size);
    //    //返回结构体
    //    return BytesToStuct(date, type);
    //}

    ///// <summary>
    ///// byte数组转结构体
    ///// </summary>
    ///// <param name="bytes">byte数组</param>
    ///// <param name="type">结构体类型</param>
    ///// <returns>转换后的结构体</returns>
    //public static object BytesToStuct(byte[] bytes, Type type)
    //{
    //    //得到结构体的大小
    //    int size = Marshal.SizeOf(type);
    //    //byte数组长度小于结构体的大小
    //    if (size > bytes.Length)
    //    {
    //        //返回空
    //        return null;
    //    }
    //    //分配结构体大小的内存空间
    //    IntPtr structPtr = Marshal.AllocHGlobal(size);
    //    //将byte数组拷到分配好的内存空间
    //    Marshal.Copy(bytes, 0, structPtr, size);
    //    //将内存空间转换为目标结构体
    //    object obj = Marshal.PtrToStructure(structPtr, type);
    //    //释放内存空间
    //    Marshal.FreeHGlobal(structPtr);
    //    //返回结构体
    //    return obj;
    //}

    public static T GetObject<T>(byte[] date, uint index)
    {
        return Marshal.PtrToStructure<T>(Marshal.UnsafeAddrOfPinnedArrayElement(date, (int)index));
    }

    public static uint GetSize(object o)
    {
        if (o is byte[])
        {
            return (uint)((byte[])o).Length;
        }
      
        return (uint)Marshal.SizeOf(o.GetType());
    }

    public static int Sizeofc(void * c)
    {
        //int num = 0;
        //while (c != null && *c != 0)
        //{
        //    num++;
        //}
        //return num;
        return 1;
    }

    ///// <summary> 
    ///// 将一个object对象序列化，返回一个byte[]         
    ///// </summary> 
    ///// <param name="obj">能序列化的对象</param>         
    ///// <returns></returns> 
    //public static byte[] ObjectToBytes(object obj)
    //{
    //    using (MemoryStream ms = new MemoryStream())
    //    {
    //        IFormatter formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); return ms.GetBuffer();
    //    }
    //}

    ///// <summary> 
    ///// 将一个序列化后的byte[]数组还原         
    ///// </summary>
    ///// <param name="Bytes"></param>         
    ///// <returns></returns> 
    //public static object BytesToObject(byte[] Bytes)
    //{
    //    using (MemoryStream ms = new MemoryStream(Bytes))
    //    {
    //        IFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(ms);
    //    }
    //}

    public static byte[] StringTobyte(string s)
    {
        return Encoding.GetEncoding("GB2312").GetBytes(s);
    }

    public static IntPtr StringTobyteAdrr(string s)
    {
        return getBytePtr( StringTobyte(s));
    }

    public static unsafe string String(byte[] date, long index)
    {
        IntPtr str = getBytePtr(date, (uint)index);
        return String((sbyte*)str);
    }

    public static unsafe string String(byte[] date, long index,int len)
    {
        IntPtr str = getBytePtr(date, (uint)index);
        return String((byte*)str, len);
    }

    public static unsafe string String(byte* str, int len)
    {
        return Encoding.GetEncoding("GB2312").GetString(str, len).Replace(@"\0", "");
        //return Marshal.PtrToStringAuto((IntPtr)str);
    }

    public static unsafe string String(byte* str, uint len)
    {
        return String(str, (int)len);
        
    }

    public static unsafe string String(sbyte* str)
    {
        return String((byte*)str, _strnlen_s(str));
    }

    public static Dictionary<string,FILE> files=new Dictionary<string, FILE>();

    public static string FormatPathString(string path, char sep = '/')
    {
        if (!path.Contains(DefineConstants.RootPath))
            path = DefineConstants.RootPath + "/" + path;
        path = path.Replace("//", "/");
        try
        {
          return  Path.GetFullPath(path);
        }catch(Exception e)
        {
            logw(e.Message);
            return e.Message;
        }
    }

    public static FILE fopen(string path, string mode,int offset=0)
    {
        path = FormatPathString(path);
       
        if (files.ContainsKey(path))
        {
            FILE file = files[path];
            file.Seek(offset, SeekOrigin.Begin);
            return files[path];
        }
        else
        {
            if (File.Exists(path))
            {
                FILE file = new FILE(path, FileMode.Open);
                files.Add(path, file);
                return file;
            }
            else
            {
                try
                {
                    //string dir = Path.GetDirectoryName(path);
                    //if(!Directory.Exists(dir))
                    //{
                    //Directory.CreateDirectory(dir);
                    //}
                    FILE file = new FILE(path, FileMode.OpenOrCreate);
                    files.Add(path, file);

                    return file;
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                    return null;
                }
            }

        }
    }


    public static long fseek(FILE file, uint offset, int seek)
    {
       return file.Seek(offset, (SeekOrigin)seek);
        //file.brLength 
    }

    public static uint fread(byte[] date, int offset, int cound, FILE file)
    {
        for (int i = 0; i < cound; i++)
        {
            date[i + offset - 1] = (byte)file.ReadByte();
        }
        //int n = file.Read(date, offset - 1, cound);
        //if (n != cound)
        //{
        //    Debug.LogError("fread LogError num: " + (cound - n));
        //}
        return (uint)cound;
    }

    public static uint fread(void* value, int offset, int cound, FILE file)
    {
        byte[] b = new byte[cound];
        fread(b, offset, cound, file);
        memcpy(value, (void*)getBytePtr(b), (uint)cound);
        return (uint)cound;
    }

    public static uint fread( elf_sec_head_t* value, int offset, int cound, FILE file)
    {
        byte[] b = new byte[cound];
        fread(b, offset, cound, file);
        *value = *((elf_sec_head_t*)getBytePtr(b));
        return (uint)cound;
    }

    public static uint fread(out mrp_head_info value, int offset, int cound, FILE file)
    {
        byte[] b = new byte[cound];
        fread(b, offset, cound, file);
        value =*((mrp_head_info*)getBytePtr( b));
        return (uint)cound;
    }

    public static uint freadElf(out elf_head_t value, int offset, int cound, FILE file)
    {
        byte[] b = new byte[cound];
        fread(b, offset, cound, file);
        value = *((elf_head_t*)getBytePtr(b));
        return (uint)cound;
    }

    public static uint fread(out uint obj, int offset, int cound, FILE file)
    {
        byte[] b = new byte[cound];
        fread(b, offset, cound, file);
        obj =*((uint*)getBytePtr(b));
        return (uint)cound;
    }

    public static uint fread(out ushort obj, int offset, int cound, FILE file)
    {
        byte[] b = new byte[cound];
        fread(b, offset, cound, file);
        obj = *((ushort*)getBytePtr(b));
        return (uint)cound;
    }

    public static uint fread(out string obj, int offset, int cound, FILE file)
    {
        byte[] b = new byte[cound];
        fread(b, offset, cound, file);
        obj = String((byte*)getBytePtr(b),cound);
        return (uint)cound;
    }

    public static void fclose(FILE file)
    {
        //file.Flush();
        //file.Close();
    }

    public static void allfclose()
    {
        foreach (var item in files)
        {
            item.Value.Close();
        }
    }

    //GB2312转换成unicode编码
    public static string GB2Unicode(string str)
    {
        string Hexs = "";
        string HH;
        Encoding GB = Encoding.GetEncoding("GB2312");
        Encoding unicode = Encoding.Unicode;
        byte[] GBBytes = GB.GetBytes(str);
        for (int i = 0; i < GBBytes.Length; i++)
        {
            HH = "%" + GBBytes[i].ToString("X");
            Hexs += HH;
        }
        return Hexs;
    }
    //unicode编码转换成GB2312汉字
    public static string UtoGB(string str)
    {
        string[] ss = str.Split('%');
        byte[] bs = new Byte[ss.Length - 1];
        for (int i = 1; i < ss.Length; i++)
        {
            bs[i - 1] = Convert.ToByte(Convert2Hex(ss[i]));   //ss[0]为空串  
        }
        char[] chrs = System.Text.Encoding.GetEncoding("GB2312").GetChars(bs);
        string s = "";
        for (int i = 0; i < chrs.Length; i++)
        {
            s += chrs[i].ToString();
        }
        return s;
    }
    private static string Convert2Hex(string pstr)
    {
        if (pstr.Length == 2)
        {
            pstr = pstr.ToUpper();
            string hexstr = "0123456789ABCDEF";
            int cint = hexstr.IndexOf(pstr.Substring(0, 1)) * 16 + hexstr.IndexOf(pstr.Substring(1, 1));
            return cint.ToString();
        }
        else
        {
            return "";
        }
    }

    public static string UCS2ByteRev(sbyte* str)
    {
        sbyte temp;
        int i = 0;

        //char[] str = strS.ToCharArray();

        while (str[i] != 0 || str[i + 1] != 0)
        {
            temp = str[i];
            str[i] = str[i + 1];
            str[i + 1] = temp;
            i += 2;
        }

        return String(str);
    }
    public static uint UCS2_strlen(sbyte* txt)
    {
        int i = 0;

        while (txt[i]!=0 || txt[i + 1]!=0)
        {
            i += 2;
        }

        return (uint)i;
    }

    public static int access(string fullpathname, int f_OK)
    {
        //bool isTure = Directory.Exists(fullpathname);
        bool isTure = File.Exists(fullpathname);
        return isTure?0:-1;
    }
    public static int accessDir(string fullpathname, int f_OK)
    {
        bool isTure = Directory.Exists(fullpathname);
        return isTure ? 0 : -1;
    }
    public static int fileId = 3;
    public static List< FileStream> file=new List<FileStream>();
    public static int open(string fullpathname, int new_mode, uint mode)
    {
        if (GameStart.isPrint)
            print("Open:" + fullpathname + "   FileMode:" + Enum.GetName(typeof(FileMode), new_mode));

        //FileInfo files = new FileInfo(FormatPathString(fullpathname));
        string path = FormatPathString(fullpathname);
        if (!File.Exists(path))
        {
            if (new_mode <= GlobalMembers.O_APPEND)
            {
                {
                    Debug.LogWarning("No File: " + fullpathname + "  new_mode:" + new_mode + " mode:" + mode);
                    //return -1;

                }
            }
        }
        FILE f = fopen(fullpathname, "rb");
        if (f == null)
        {
            Debug.LogWarning("No File: " + fullpathname);
            return -1;
        }
        else
        {
            switch(new_mode)
            {
                case GlobalMembers.O_RDONLY:
                    
                case GlobalMembers.O_WRONLY:
                    
                case GlobalMembers.O_RDWR:
                    break;
                case GlobalMembers.O_APPEND:
                    f.Seek(0, SeekOrigin.End);
                    break;

            }
            if (!file.Contains(f))
            {
                f.id = fileId++;
                file.Add(f);
            }

            if (GameStart.isLog)
                Debug.LogWarning("Open:" + fullpathname + "   FileMode:" + Enum.GetName(typeof(FileMode), new_mode) + "  id: " + f.id.ToString());
            return f.id;
        }
    }

    public static int close( uint v)
    {
        //if(file !=null)
        //   file =null;
        return 0;
    }

    //public static int Stat(string path, stat s1)
    //{
    //    FileStream file = fopen(path,"rb");
    //    path = Application.streamingAssetsPath + "/" + path;
    //    if (File.Exists(path))
    //        s1.st_mode = 1;
    //    else if (Directory.Exists(path))
    //        s1.st_mode = 2;
    //    if(file!=null)
    //    s1.st_size = (uint)file.Length;
    //    else
    //    {
    //        print("Not find file:"+ path);
    //    }
    //    return access(path ,0);
    //}
    public static int Stat(string path, stat s1)
    {

        print(" file Stat:" + path);
        string p = path;
        path = FormatPathString(path);
        if (File.Exists(path))
        {
            //FileStream file = fopen(p, "rb");
            FileInfo file = new FileInfo(path);
            s1.st_mode = 1;
            s1.st_size = (uint)file.Length;
            
            return 0;
        }
        else if (Directory.Exists(path))
        {
            s1.st_mode = 2;
            return 0;
        }
        else
        {
            print("Not find file:" + path);
        }
        return -1;
    }

    public static bool S_ISREG(ushort st_mode)// 是否是一个常规文件.
    {
        return st_mode == 1;
    }

    public static bool S_ISDIR(ushort st_mode)// 是否是一个目录
    {
        return st_mode == 2;
    }

    //#region Decompress

    //private static void decompressFile(string inFile, string outFile)
    //{
    //    FileStream outFileStream = new FileStream(outFile, System.IO.FileMode.Create);
    //    zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFileStream);
    //    FileStream inFileStream = new FileStream(inFile, System.IO.FileMode.Open);
    //    try
    //    {
    //        CopyStream(inFileStream, outZStream);
    //    }
    //    finally
    //    {
    //        outZStream.Close();
    //        outFileStream.Close();
    //        inFileStream.Close();
    //    }
    //}

    //private static void decompressFile(byte[] inFile, string outFile)
    //{
    //    FileStream outFileStream = new FileStream(outFile, System.IO.FileMode.Create);
    //    zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFileStream);
    //    MemoryStream inFileStream = new MemoryStream(inFile);
    //    try
    //    {
    //        CopyStream(inFileStream, outZStream);
    //    }
    //    finally
    //    {
    //        outZStream.Close();
    //        outFileStream.Close();
    //        inFileStream.Close();
    //    }
    //}

    //public static void CopyStream(System.IO.Stream input, ZOutputStream output)
    //{
    //    byte[] buffer = new byte[2000];
    //    int len;

    //    while ((len = input.Read(buffer, 0, 2000)) > 0)
    //    {
    //        output.Write(buffer, 0, len);
    //    }
    //    output.Flush();
    //}

    //public static byte[] DecompressZlib(byte[] sourceByte, uint size = 4096)
    //{
    //    //MemoryStream inputStream = new MemoryStream(sourceByte);
    //    byte[] result = null;
    //    using (var stream = new MemoryStream(sourceByte, 2, sourceByte.Length - 2))
    //    using (var inflater = new DeflateStream(stream, CompressionMode.Decompress))
    //    using (MemoryStream outStream = new MemoryStream())
    //    {
    //        using (InflaterInputStream inf = new InflaterInputStream(inflater))
    //        {
    //            inf.CopyTo(outStream);
    //        }
    //        result = outStream.ToArray();
    //    }
    //    return result;
    //}

    //public static byte[] ungzip(ref byte[] src, uint srcLen, ref byte[] dst, ref uint dstLen)
    //{
    //    ////UnpackFiles(src, @"C:\test");
    //    //// decompressFile(src, Application.streamingAssetsPath + "/h");
    //    //dst = DeflateDecompress(src);
    //    //dstLen = (uint)dst.Length;

    //    return dst;
    //}

    //public static bool UnpackFiles(byte[] sourceByte, string dir)
    //{
    //    try
    //    {
    //        if (!Directory.Exists(dir))
    //        {
    //            Directory.CreateDirectory(dir);
    //        }
    //        MemoryStream inputStream = new MemoryStream(sourceByte);
    //        //ZipInputStream s = new ZipInputStream(File.OpenRead(file));
    //        ZipInputStream s = new ZipInputStream(inputStream);
    //        ZipEntry theEntry;
    //        while ((theEntry = s.GetNextEntry()) != null)
    //        {
    //            string directoryName = Path.GetDirectoryName(theEntry.Name);
    //            string fileName = Path.GetFileName(theEntry.Name);
    //            if (directoryName != string.Empty)
    //            {
    //                Directory.CreateDirectory(dir + directoryName);
    //            }
    //            if (fileName != string.Empty)
    //            {
    //                FileStream streamWriter = File.Create(dir + theEntry.Name);
    //                int size = 2048;
    //                byte[] data = new byte[2048];
    //                while (true)
    //                {
    //                    size = s.Read(data, 0, data.Length);
    //                    if (size > 0)
    //                    {
    //                        streamWriter.Write(data, 0, size);
    //                    }
    //                    else
    //                    {
    //                        break;
    //                    }
    //                }
    //                streamWriter.Close();
    //            }
    //        }
    //        s.Close();
    //        return true;
    //    }
    //    catch (Exception)
    //    {
    //        throw;
    //    }
    //}

    //public static byte[] GzipCompress(byte[] sourceByte, uint size = 4096)
    //{
    //    MemoryStream outStream = new MemoryStream();
    //    GZipOutputStream outZStream = new GZipOutputStream(outStream);

    //    MemoryStream inputStream = new MemoryStream(sourceByte);
    //    //GZipInputStream inputZStream = new GZipInputStream(inputStream);

    //    byte[] buffer = new byte[2000];
    //    int len;
    //    while ((len = inputStream.Read(buffer, 0, 2000)) > 0)
    //    {
    //        outZStream.Write(buffer, 0, len);
    //    }
    //    outZStream.Flush();

    //    byte[] outputBytes = new byte[outZStream.Length];
    //    outZStream.Position = 0;
    //    outZStream.Read(outputBytes, 0, outputBytes.Length);
    //    outZStream.Close();
    //    inputStream.Close();
    //    return outputBytes;
    //}

    //private static byte[] deCompressBytes(byte[] sourceByte, uint size = 4096)
    //{
    //    MemoryStream inputStream = new MemoryStream(sourceByte);
    //    Stream outputStream = deCompressStream(inputStream);
    //    byte[] outputBytes = new byte[outputStream.Length];
    //    outputStream.Position = 0;
    //    outputStream.Read(outputBytes, 0, outputBytes.Length);
    //    outputStream.Close();
    //    inputStream.Close();
    //    return outputBytes;
    //}

    //private static Stream deCompressStream(Stream sourceStream)
    //{
    //    MemoryStream outStream = new MemoryStream();
    //    ZOutputStream outZStream = new ZOutputStream(outStream);
    //    CopyStream(sourceStream, outZStream);
    //    outZStream.finish();
    //    return outStream;
    //}

    //public static byte[] ZLibDotnetDecompress(byte[] data, uint size=4096)
    //{
    //    MemoryStream compressed = new MemoryStream(data);
    //    ZInputStream inputStream = new ZInputStream(compressed);
    //    long len= size;
    //    byte[] result = new byte[size];   // 由于ZInputStream 继承的是BinaryReader而不是Stream, 只能提前准备好输出的 buffer 然后用 read 获取定长数据。
    //                                      // inputStream.read(result, 0, result.Length); // 注意这里的 read 首字母是小写
    //    List<byte> OutDate = new List<byte>();
    //    while ((len=inputStream.Read(result, 0, (int)len)) > 0)
    //    {
    //        result = new byte[len];
    //        OutDate.AddRange(result);
    //    }
    //    data = OutDate.ToArray();
    //    return data;
    //}

    //public static byte[] DeflateDecompress(byte[] Buffer,uint size=2000)
    //{
    //    int data = 0;
    //    int stopByte = -1;

    //    MemoryStream intms = new MemoryStream(Buffer);
    //    zlib.ZInputStream inZStream = new zlib.ZInputStream(intms);
    //    inZStream.FlushMode = GameStart.FlushMode;
    //    //int count = 1024 * 1024;
    //    List< byte> inByteList = new List<byte>();
    //    int i = 0;
    //    while (stopByte != (data = inZStream.Read()))
    //    {
    //        inByteList.Add((byte)data);
    //        //inByteList[i] = (byte)data;
    //        i++;
    //    }
    //    inZStream.Close();
    //    return inByteList.ToArray ();

    //}

    //public static byte[] DotnetDecompress(byte[] datas, uint datasSize = 2000)
    //{
    //    byte[] bytes = new byte[0];
    //    MemoryStream compressed = new MemoryStream(datas);
    //    ZInputStream zIn = new ZInputStream(compressed);

    //    int curPosition = 0;
    //    int size1 = 4096;
    //    Byte[] data = new Byte[size1];

    //    while (true)
    //    {
    //        int size = zIn.Read(data, 0, data.Length);
    //        if (size > 0)
    //        {
    //            //if(size<= size1)
    //            curPosition += size;
    //            Byte[] tempBytes = new Byte[bytes.LongLength + size];

    //            bytes.CopyTo(tempBytes, 0);
    //            data.CopyTo(tempBytes, size);

    //            bytes = tempBytes;

    //        }
    //        else
    //        {
    //            break;
    //        }
    //    }

    //    return bytes;
    //}

    //#endregion


    public static dirent readdir(DIR pDir)
    {
        FileSystemInfo fsinfo = pDir.GetNextFile();
        if (fsinfo is DirectoryInfo)     //判断是否为文件夹
        {
            //Director(fsinfo.FullName);//递归调用
        }
        else
        {
            if (fsinfo !=null)
            {
                print(fsinfo.FullName);//输出文件的全部路径
                dirent dir = new dirent();
                dir.d_name = (byte*)StringTobyteAdrr(fsinfo.Name);
                return dir;
            }  
        }

        return null;
    }

    public static uint closedir(DIR pDir)
    {
        if(DIR.keyValuePairs.ContainsKey(pDir.handle))
        {
            DIR.keyValuePairs.Remove(pDir.handle);
            return 0;
        }
        else
        {
            return uint.MaxValue;
        }
          
    }

    public static DIR opendir(string v)
    {
        v=FormatPathString(v);
        DirectoryInfo DirectoryInfo = new DirectoryInfo(v);
        DIR dIR = new DIR( DirectoryInfo);
        return dIR;
    }
}

public class Console
{

    public static void Write(string info1, object info2 = null, object info3 = null, object info4 = null, object info5 = null, object info6 = null, object info7 = null, object info8 = null, object info9 = null, object info10 = null, object info11 = null)
    {
        if (GameStart.isPrint)
            Debug.Log(string.Format(info1, info2, info3, info4, info5, info6, info7, info8, info9,info10,info11));
    }

    public static void Write(sbyte info1, object info2 = null, object info3 = null)
    {
        if (GameStart.isPrint)
            Debug.Log(string.Format("{0}: {1}", info1, info2));
    }
}

public class FILE : FileStream
{
    public BinaryReader binaryReader;
    public long brLength;
    public int id;
    public FILE(string path, FileMode fileMode) :base(path, fileMode)
    {
        //binaryReader = new BinaryReader(this);
        //brLength = binaryReader.BaseStream.Length;
        //FileStream file = File.OpenRead(path);
    }

}

public class timeval
{
    internal long tv_sec;
    internal long tv_usec;
    public TimeSpan timeSpan;
    public timeval()
    {
        //timeSpan = TimeSpan.FromMilliseconds;
        //tv_sec = timeSpan.Seconds ;
        //tv_usec = timeSpan.Milliseconds;
        
    }
}

public class stat
{
    public uint st_dev;
    public ushort st_ino;
    public  ushort st_mode;
    public short st_nlink;
    public short st_uid;
    public short st_gid;
    public uint st_rdev;
    public uint st_size;
    public long st_atime;
    public long st_mtime;
    public long st_ctime;
}

public class DIR
{
    public static Dictionary<uint, DIR> keyValuePairs = new Dictionary<uint, DIR>();
    public static uint CHandle;
    public uint handle;
    public DirectoryInfo DirectoryInfo;
    public DIR(uint handle)
    {
        this.handle=  handle;
        DirectoryInfo = keyValuePairs[handle].DirectoryInfo;
        fsinfos= keyValuePairs[handle].fsinfos;
        _index = keyValuePairs[handle]._index;
    }

    public static DIR Get(uint handle)
    {
        return keyValuePairs[handle];
    }

    public DIR(DirectoryInfo DirectoryInfo)
    {
        this.DirectoryInfo = DirectoryInfo;
        this.handle = ++CHandle;
        if(!keyValuePairs.ContainsKey(handle))
           keyValuePairs.Add(handle, this);
        fsinfos = DirectoryInfo.GetFileSystemInfos("*.mrp");
    }

    public FileSystemInfo[] fsinfos;
    int _index;

    public FileSystemInfo GetNextFile()
    {
        if (_index < fsinfos.Length)
            return fsinfos[_index++];
        return null;
    }
}

public unsafe class dirent
{
    public byte* d_name;
}

//[StructLayoutAttribute(LayoutKind.Explicit, Pack = 1)]
public struct union
{
    //[FieldOffset(0)]
    public ulong U;
    //[FieldOffset(0)]
    public double F;
}
